package com.distributed.tcp.server;

import com.distributed.tcp.manager.DeviceConnectionManager;
import com.distributed.tcp.manager.MessageHandler;
import com.distributed.tcp.model.ClientChannelAttrs;
import com.distributed.tcp.model.DeviceConnection;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;

@Slf4j
public class TcpServerHandler extends ChannelInboundHandlerAdapter {
    private final int port;
    private final DeviceConnectionManager connectionManager;
    private final MessageHandler messageHandler;
    private final ExecutorService executor;

    public TcpServerHandler(int port, DeviceConnectionManager connectionManager,
                           MessageHandler messageHandler, ExecutorService executor) {
        this.port = port;
        this.connectionManager = connectionManager;
        this.messageHandler = messageHandler;
        this.executor = executor;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        // 客户端连接成功，注册连接 //TODO 可以配置nginx 判断是否有效连接，或者SSL证书
        //connectionId = connectionManager.registerConnection(ctx.channel(), port);
        log.info("客户端连接: {}", ctx.channel().remoteAddress());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg == null) return;

        String message = msg.toString();
        log.debug("收到消息 [{}]: {}", port,  message);

        // 提交到线程池处理，增加拒绝策略处理
        try {
            executor.submit(() -> {
                try {
                    messageHandler.handleMessage(ctx.channel(),port, message, connectionManager);
                } catch (Exception e) {
                    log.error("处理消息失败", e);
                }
            });
        } catch (RejectedExecutionException e) {
            log.error("线程池繁忙，无法处理消息 ", e);
            ctx.writeAndFlush("服务器繁忙，请稍后再试\r\n"); // 反馈给客户端
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        // 处理空闲事件
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                // 客户端长时间未发送数据（包括心跳），关闭连接
                log.info("客户端{}读空闲超时（未收到心跳），关闭连接");
                ctx.close();
            }
            //不需要服务器主动发心跳
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        String deviceCode = ctx.channel().attr(ClientChannelAttrs.DEVICE_CODE).get();
        // 客户端断开连接
        if (StringUtils.isNotBlank(deviceCode)) {
            log.info("客户端断开连接: {}，连接ID: {}", ctx.channel().remoteAddress(), deviceCode);
            connectionManager.removeConnection(deviceCode);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}
